package cn.b.sky.admin.controller;

import cn.b.sky.admin.exception.ManagementException;
import cn.b.sky.admin.model.FunctionGroup;
import cn.b.sky.admin.service.FunctionGroupService;
import cn.b.sky.admin.service.InitializationScriptService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Controller
@RequestMapping(value = "/management/initializationScript/*")
public class InitializationScriptController extends BaseController {

  private static final Logger LOG = LoggerFactory.getLogger(InitializationScriptController.class);

  @Resource
  InitializationScriptService initializationScriptService;

  @Resource
  FunctionGroupService functionGroupService;

  @RequestMapping("initializationScriptPage")
  public String initializationScriptPage(Model model, HttpServletRequest request, String navTabId) {
    model.addAttribute(NAVTABID, navTabId);
    return "admin/initializationScript/initializationScript";
  }

  @RequestMapping(value = "exportScript")
  public void exportScript(String navTabId, String tcLwIds, HttpServletRequest request, HttpServletResponse response) {
    try {
      List<File> files = new ArrayList<File>();
      //查询功能组
      List<FunctionGroup> groups = functionGroupService.getAllFunctionGroups();
      for (FunctionGroup group : groups) {
        if (!StringUtils.isBlank(group.getTableNameList())) {
          String[] tables = group.getTableNameList().split(",");
          String script = initializationScriptService.getDataScript(tables, group.getFunctionGroupCode());
          File file = new File(StringUtils.leftPad(group.getSequenceNum().toString(), 4, '0') + "-"
              + group.getFunctionGroupCode() + ".sql");
          writeFile(script, file);
          files.add(file);
        }
      }
      String fileName = "InitializationScript.zip";
      //在服务器端创建打包下载的临时文件
      String outFilePath = request.getSession().getServletContext().getRealPath("/") + "/initTempFile/";
      createFile(outFilePath, fileName);
      File file = new File(outFilePath + fileName);
      //文件输出流
      FileOutputStream outStream;
      outStream = new FileOutputStream(file);
      //压缩流
      ZipOutputStream toClient = new ZipOutputStream(outStream);
      zipFile(files, toClient);
      toClient.close();
      outStream.close();
      this.downloadFile(file, response, true);

    } catch (ManagementException e) {
      LOGGER.error("{}", e);
    } catch (IOException e) {
      LOGGER.error("{}", e);
    }
  }

  public void createFile(String path, String fileName) {
    //path表示你所创建文件的路径
    File f = new File(path);
    f.mkdirs();
    /*if(!f.exists()){
    f.mkdirs();
    } */
    // fileName表示你创建的文件名；为txt类型；
    File file = new File(f, fileName);
    if (!file.exists()) {
      try {
        file.createNewFile();
      } catch (IOException e) {
        LOG.error("", e);
      }
    }
  }

  /**
   * 压缩文件列表中的文件
   * @param files
   * @param outputStream
   * @throws IOException
   */
  public static void zipFile(List<File> files, ZipOutputStream outputStream) throws IOException, ManagementException {
    try {
      int size = files.size();
      //压缩列表中的文件
      for (int i = 0; i < size; i++) {
        File file = files.get(i);
        zipFile(file, outputStream);
      }
    } catch (IOException e) {
      throw e;
    }
  }

  /**
  * 将文件写入到zip文件中
  * 
  * @param inputFile
  * @param outputstream
  * @throws Exception
  */
  public static void zipFile(File inputFile, ZipOutputStream outputstream) throws IOException, ManagementException {
    try {
      if (inputFile.exists()) {
        if (inputFile.isFile()) {
          FileInputStream inStream = new FileInputStream(inputFile);
          BufferedInputStream bInStream = new BufferedInputStream(inStream);
          ZipEntry entry = new ZipEntry(inputFile.getName());
          outputstream.putNextEntry(entry);

          final int MAX_BYTE = 50 * 1024 * 1024; // 最大的流为50M
          long streamTotal = 0; // 接受流的容量
          int streamNum = 0; // 流需要分开的数量
          int leaveByte = 0; // 文件剩下的字符数
          byte[] inOutbyte; // byte数组接受文件的数据

          streamTotal = bInStream.available(); // 通过available方法取得流的最大字符数
          streamNum = (int) Math.floor(streamTotal / MAX_BYTE); // 取得流文件需要分开的数量
          leaveByte = (int) streamTotal % MAX_BYTE; // 分开文件之后,剩余的数量

          if (streamNum > 0) {
            for (int j = 0; j < streamNum; ++j) {
              inOutbyte = new byte[MAX_BYTE];
              //读入流,保存在byte数组
              bInStream.read(inOutbyte, 0, MAX_BYTE);
              outputstream.write(inOutbyte, 0, MAX_BYTE); // 写出流
            }
          }
          //写出剩下的流数据
          inOutbyte = new byte[leaveByte];
          bInStream.read(inOutbyte, 0, leaveByte);
          outputstream.write(inOutbyte);
          outputstream.closeEntry(); // Closes the current ZIP entry
          //and positions the stream for
          //writing the next entry
          bInStream.close(); // 关闭
          inStream.close();
        }
      } else {
        throw ManagementException.newException("文件不存在!", null);
      }
    } catch (IOException e) {
      throw e;
    }
  }

  /**
  * 下载文件
  * @param file
  * @param response
  */
  public void downloadFile(File file, HttpServletResponse response, boolean isDelete) {
    try {
      // 以流的形式下载文件。
      BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
      byte[] buffer = new byte[fis.available()];
      fis.read(buffer);
      fis.close();
      // 清空response
      response.reset();
      OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
      response.setContentType("application/octet-stream");
      response.setHeader("Content-Disposition", "attachment;filename="
          + new String(file.getName().getBytes("UTF-8"), "ISO-8859-1"));
      toClient.write(buffer);
      toClient.flush();
      toClient.close();
      if (isDelete) {
        file.delete(); //是否将生成的服务器端文件删除
      }
    } catch (IOException ex) {
      LOG.error("", ex);
    }
  }

  public File createFile(String fileName) {
    File file = new File(fileName);
    return file;
  }

  public boolean writeFile(String content, File fileName) throws IOException {
    RandomAccessFile mm = null;
    boolean flag = false;
    FileOutputStream o = null;
    try {
      o = new FileOutputStream(fileName);
      o.write(content.getBytes("UTF-8"));
      o.close();
      flag = true;
    } catch (IOException e) {
      throw e;
    } finally {
      if (mm != null) {
        mm.close();
      }
    }
    return flag;
  }

}
